home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1995-03-26 | 7.5 KB | 119 lines | [ TEXT/MMCC]
//------------------------------------------------------------------------------ // File: arcball.cp // Date: 9/18/94 // Author: Bretton Wade // (C) copyright Cornell Program of Computer Graphics // // Description: this file contains the class methods for Ken Shoemake's // ArcBall rotation controller // // This class presumes the existence of a number of drawing // routines, and a graphics system that uses Virtual Device // Coordinates ranging from -1 to 1 in both x and y. The // ArcBall itself and the feedback are projected orthographically // onto the screen. // //------------------------------------------------------------------------------ #include "draw.h" #include "colors.h" #include "arcball.h" #include "quaternion_3d.h" //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ arcball::arcball (const point_2d ¢, real rad) : interface () // normal constructor { // begin center = vector_2d (cent); // store the center point_2d of the arcball radius = rad; // store the radius of the arcball } // end //------------------------------------------------------------------------------ // take begin of drag //------------------------------------------------------------------------------ void arcball::Click (const point_2d &pt) // the first point_3d in the arc { // begin start_vec = MapToSphere (pt - center); // map the point_3d to the arcball sphere start_pt = point_2d (start_vec[X], start_vec[Y]) + center; // save the mapped vector_3d as a point_3d too } // end //------------------------------------------------------------------------------ // complete drag //------------------------------------------------------------------------------ matrix_3d arcball::Drag (const point_2d &pt) // the second point_3d in the arc { // begin end_vec = MapToSphere (pt - center); // map the point_3d to the arcball sphere end_pt = point_2d (end_vec[X], end_vec[Y]) + center; // save the mapped vector_3d as a point_3d too return Quaternion (start_vec, end_vec); // return the matrix_3d equivalent to the quaternion } // end //------------------------------------------------------------------------------ // draw the sphere of the arcball //------------------------------------------------------------------------------ void arcball::DrawBackground (void) const // draw the sphere { // begin RGBBackColor (&HILITE_COLOR); // set the background color RGBForeColor (&MID_HILITE_COLOR); // set the foreground color point_2d A = point_2d (-radius, -radius) + center, // compute the bottom left point_3d of a rectangle B = point_2d (radius, radius) + center; // compute the top right of a rectangle Circle (A, B); // draw a circle inside the rectangle in the view RGBBackColor (&WHITE); // restore the background color, no need to restore the foreground color for me RGBForeColor (&BLACK); // reset the foreground color } // end //------------------------------------------------------------------------------ // draw all the arcball feedback //------------------------------------------------------------------------------ void arcball::DrawForeground (void) const // draw the arcball interface { // begin RGBForeColor (&BLUE); // set the foreground color DrawArc (5); // draw the great arc on the arcball sphere RGBForeColor (&RED); // set the foreground color CrossHair (end_pt); // draw a crosshair at the end point_3d RGBForeColor (&BLACK); // reset the foreground color CrossHair (start_pt); // draw a crosshair at the atrt point_3d } // end //------------------------------------------------------------------------------ // compute the segments on the feedback arc //------------------------------------------------------------------------------ void arcball::ComputeArc (short segs, const vector_3d &a, const vector_3d &b) const // compute the arc between two points with the given number of segments { // begin if (segs) // if more segments need to be computed { // begin vector_3d bisector = (a + b).Normalize () * radius; // compute the vector_3d that bisects the angle between 'a' and 'b' ComputeArc (segs - 1, a, bisector); // compute the sub arc from 'a' to the 'bisector' ComputeArc (segs - 1, bisector, b); // compute the sub arc from the 'bisector' to 'b' } // end else // otherwise LineTo (point_2d (b[X], b[Y]) + center); // draw a line to the segment endpoint } // end //------------------------------------------------------------------------------ // draw the feedback arc //------------------------------------------------------------------------------ void arcball::DrawArc (short numsegs) const // draw the arc between the two points { // begin MoveTo (start_pt); // move the pen to the start_vec point_3d ComputeArc (numsegs, start_vec, end_vec); // compute the arc and draw each segment } // end //------------------------------------------------------------------------------ // map some click point_3d to the arcball sphere //------------------------------------------------------------------------------ vector_3d arcball::MapToSphere (const point_2d &pt) // compute the intersection pt of the arcball with a line to the point_3d { // begin real r = (pt[X] * pt[X]) + (pt[Y] * pt[Y]), // compute the square of the length of the vector_3d to the point_3d from the center radsq = radius * radius; // compute the square of the radius of the arcball sphere if (r > radsq) // if the point_3d is mapped outside of the arcball sphere { // begin real s = radius / SQRT (r); // compute a normalizing factor return vector_3d (pt[X] * s, pt[Y] * s, R(0.0)); // return the "normalized" vector_3d, a point_3d on the sphere } // end else // alse return vector_3d (pt[X], pt[Y], SQRT (radsq - r)); // return a vector_3d to a point_3d mapped inside the sphere } // end //------------------------------------------------------------------------------